package org.luxor.system.security;

import org.luxor.commons.core.utils.StringUtils;
import org.luxor.commons.security.component.GrantedAuthorityImpl;
import org.luxor.commons.security.entity.UserSubject;
import org.luxor.system.entity.SysRoleEntity;
import org.luxor.system.entity.SysUserEntity;
import org.luxor.system.service.ISysRoleService;
import org.luxor.system.service.ISysUserService;
import org.luxor.system.transform.UserTransform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.HashSet;
import java.util.stream.Collectors;

/**
 * 用于Security框架,加载登陆者用户数据的核心接口
 *
 * @author yanxinming
 */
@Service
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
    private static final Logger logger = LoggerFactory.getLogger(UserDetailsService.class);

    @Resource
    private ISysUserService sysUserService;
    @Resource
    private ISysRoleService sysRoleService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (StringUtils.isBlank(username)) {
            logger.warn("登陆账号或密码，不能为空!", username);
            throw new UsernameNotFoundException("登陆账号或密码，不能为空!");
        }
        SysUserEntity sysUser = sysUserService.getByUserName(username);
        if (sysUser == null || sysUser.getId() == null) {
            logger.warn("账号[{}]不存在", username);
            throw new UsernameNotFoundException(String.format("账号[%s]不存在", username));
        }
        // 账号密码
        String passWord = sysUser.getPassword();
        if (StringUtils.isBlank(passWord)) {
            logger.error("账号[{}]的密码，不能为空", username);
            throw new UsernameNotFoundException(String.format("账号[%s]的密码，不能为空", username));
        }

        // 所属角色权限码
        Collection<GrantedAuthorityImpl> authorities = new HashSet<>(3);
        Collection<SysRoleEntity> roles = sysRoleService.listByUserId(sysUser.getId());
        if (roles != null) {
            authorities.addAll(roles.stream().map(
                    role -> new GrantedAuthorityImpl(role.getRoleCode())
            ).collect(Collectors.toSet()));
        }

        // 登陆用户的主体信息
        UserSubject principal = UserTransform.toUserSubject(sysUser);
        // 用户角色权限
        principal.setAuthorities(authorities);
        return principal;
    }
}
